package cn.edu.xjtu.nbrash.xbarsuite.floatbutton;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

/**
 * FloatButton.java
 *
 * @author Jingkai Tang jingkaitang@gmail.com
 * @version 0.0.1 Nov 13, 2014 9:49:35 PM
 *
 */
public class FloatButton extends Button {

	private final static String TAG = FloatButton.class.getName();

	private final WindowManager windowManager;
	private final WindowManager.LayoutParams layoutParams;

	public static final double DEFAULT_WIDTH_PERCENT = 0.1;
	public static final double DEFAULT_HEIGHT_PERCENT = 0.1;
	
	public static final int DEFAUL_POSITION_X = 0;
	public static final int DEFAUL_POSITION_Y = 0;

	/**
	 * Use the default size?
	 */
	private boolean isDefault;

	/**
	 * The size of the FloatButton is absolute or not
	 */
	private boolean isAbsolute;

	/**
	 * Width of the FloatButton
	 */
	private int width;

	/**
	 * Height of the FloatButton
	 */
	private int height;

	/**
	 * The percentage that the width of FloatButton takes up the width of screen
	 */
	private double widthPercent;

	/**
	 * The percentage that the height of FloatButton takes up the height of
	 * screen
	 */
	private double heightPercent;
	
	/**
	 * The listener for click options
	 */
	private FloatButtonOnClickListener floatButtonOnClickListener;

	/**
	 * Create FloatButton By Default
	 * 
	 * @param context
	 */
	public FloatButton(Context context) {
		this(context, false, 0, 0, 0, 0, true);
	}

	/**
	 * Create FloatButton by the screen size dynamically
	 * 
	 * @param context
	 * @param widthPercent
	 * @param heightPercent
	 */
	public FloatButton(Context context, double widthPercent,
			double heightPercent) {
		this(context, false, 0, 0, widthPercent, heightPercent, false);
	}

	/**
	 * Create FloatButton by given size
	 * 
	 * @param context
	 * @param width
	 * @param height
	 */
	public FloatButton(Context context, int width, int height) {
		this(context, true, width, height, 0, 0, false);
	}

	/**
	 * The private constructor for handling all constructors
	 * 
	 * @param context
	 * @param isAbsolute
	 * @param width
	 * @param height
	 * @param widthPercent
	 * @param heightPercent
	 */
	@SuppressLint("ClickableViewAccessibility")
	private FloatButton(Context context, boolean isAbsolute, int width,
			int height, double widthPercent, double heightPercent,
			boolean isDefault) {
		super(context);

		windowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		layoutParams = new WindowManager.LayoutParams();

		this.isAbsolute = isAbsolute;
		this.width = width;
		this.height = height;
		this.widthPercent = widthPercent;
		this.heightPercent = heightPercent;
		this.isDefault = isDefault;
		this.setSize();
		this.floatButtonOnClickListener = null;

		/**
		 * window type 决定了悬浮按钮的可见优先级
		 */
		layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

		// 设置背景颜色方案
		layoutParams.format = PixelFormat.RGBA_8888;

		layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

		this.setOnTouchListener(new OnTouchListener() {
			int x = 0;
			int y = 1;
			int[] position = new int[2];
			int[] motion = new int[2];

			/*
			 * 给button加个OnClickListener之后效果并不好
			 * 
			 * 通过isMoved变量自行判断在“DOWN”与“UP”之间有没有移动过，移动过的话就不响应点击事件，否则执行点击事件
			 */
			boolean isMoved = false;

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
					case MotionEvent.ACTION_DOWN:
						isMoved = false;
						motion[x] = (int) event.getRawX();
						motion[y] = (int) event.getRawY();
						position[x] = layoutParams.x;
						position[y] = layoutParams.y;
						break;

					case MotionEvent.ACTION_MOVE:
						layoutParams.x = position[x] + (int) event.getRawX()
								- motion[x];
						layoutParams.y = position[y] + (int) event.getRawY()
								- motion[y];
						if (layoutParams.x != position[x]
								&& layoutParams.y != position[y]) {
							isMoved = true;
						}
						windowManager.updateViewLayout(FloatButton.this,
								layoutParams);
						break;

					case MotionEvent.ACTION_UP:
						if (!isMoved) {
							if (floatButtonOnClickListener != null) {
								floatButtonOnClickListener.onClick();
							}
							Log.e(TAG,
									FloatButtonOnClickListener.class.getName());
						}
						break;
				}

				return false;
			}
		});
	}

	public void add() {
		windowManager.addView(this, layoutParams);
	}

	public void remove() {
		windowManager.removeView(this);
	}

	private void setSize() {
		if (isAbsolute) {
			// do nothing
		} else {
			Display display = windowManager.getDefaultDisplay();
			Point displaySize = new Point();
			display.getSize(displaySize);
			if (isDefault) {
				width = (int) (displaySize.x * DEFAULT_WIDTH_PERCENT);
				height = (int) (displaySize.y * DEFAULT_HEIGHT_PERCENT);
			} else {
				width = (int) (displaySize.x * widthPercent);
				height = (int) (displaySize.y * heightPercent);
			}
		}
		layoutParams.width = this.width;
		layoutParams.height = this.height;
	}

	public void reSetSize() {
		this.setSize();
	}

	public void setFloatButtonOnClickListener(
			FloatButtonOnClickListener floatButtonOnClickListener) {
		this.floatButtonOnClickListener = floatButtonOnClickListener;
	}
	

	public WindowManager.LayoutParams getLayoutParams() {
		return layoutParams;
	}

}
